package com.eryos.android.cigarettecounter;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.UnknownHostException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.TextView;

import com.eryos.android.cigarettecounter.beans.History;
import com.eryos.android.cigarettecounter.beans.SmokeAverage;
import com.eryos.android.cigarettecounter.beans.SmokeCounter;
import com.eryos.android.cigarettecounter.charts.Chart;
import com.eryos.android.cigarettecounter.charts.HistoChart;
import com.eryos.android.cigarettecounter.charts.LineChart;
import com.eryos.android.cigarettecounter.tool.Tools;
import com.eryos.android.cigarettecounter.ui.ChartPopup;

/**
 * Project : CigaretteCounter Author : Olivier Combe URL : http://eryos.fr/CigaretteCounter/
 * 
 * Copyright(C)2011 - Olivier Combe
 * 
 * Licensed under the Apache License, Version 2.0(the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for
 * the specific language governing permissions and limitations under the License.
 * 
 * @version \$Revision.*\$
 * @author Olivier Combe
 */
public class HistoryActivity extends RootActivity {

    /** *************** UI Elements. *************** **/
    private TextView averageLabel;
    private TextView totalLabel;
    private TextView costLabel;
    private TextView historyTitle;
    private TextView chartTitle;
    private Gallery chartGallery;
    private ImageAdapter chartImageAdapter;

    private Button homeButton;
    private Button showStatButton;

    /** *************** Instance Variables. *************** **/
    private History type;

    private ArrayList<Chart> listOfCharts;

    private double average = -1;
    private double cost = -1;
    private int total = -1;

    /** *************** *********** *************** **/

    /**
     * Add a new chart to the activity.
     * 
     * @param chart
     *            to add
     */
    private void addChart(final Chart chart) {
        if (!listOfCharts.contains(chart)) {
            listOfCharts.add(chart);
        }
    }

    /**
     * Method used to initialize all UI elements.
     */
    @Override
    protected void initUI() {
        setContentView(R.layout.history);
        Log.d(getLogTag(), "initUI");

        listOfCharts = new ArrayList<Chart>();

        type = (History) this.getIntent().getExtras().getSerializable(History.class.toString());

        chartGallery = (Gallery) findViewById(R.id.history_charts_galery);
        averageLabel = (TextView) findViewById(R.id.history_stats_average);
        totalLabel = (TextView) findViewById(R.id.history_stats_total);
        costLabel = (TextView) findViewById(R.id.history_stats_cost);
        historyTitle = (TextView) findViewById(R.id.history_stats_title);
        chartTitle = (TextView) findViewById(R.id.history_charts_title);
        homeButton = (Button) findViewById(R.id.history_home_button);
        showStatButton = (Button) findViewById(R.id.history_other_button);

        int screenWidth = this.getWindow().getWindowManager().getDefaultDisplay().getWidth();
        int screenHeight = this.getWindow().getWindowManager().getDefaultDisplay().getHeight();

        Chart.defineChartDefaultSize(screenWidth, screenHeight);

        if (type.isWeekly()) {
            historyTitle.setText(R.string.history_weekly_title);
            showStatButton.setText(getResources().getString(R.string.home_month_stat_button_label));
        } else if (type.isMonthly()) {
            historyTitle.setText(R.string.history_monthly_title);
            showStatButton.setText(getResources().getString(R.string.home_week_stat_button_label));
        }
    }

    /**
     * Init Values(not UI)for this activity from DB / Network / etc.
     */
    @Override
    protected void initValues() {
        Log.d(getLogTag(), "initValues");

        if (type.isWeekly()) {

            average = db.getWeeklyAdapter().getAverage();
            cost = db.getWeeklyAdapter().getCost();
            total = db.getWeeklyAdapter().getCount();

            // Show chart only if network is available
            if (this.isNetworkAvailable()) {
                showWeeklyDetailChart(db.getWeeklyAdapter().getDetails(),
                        getResources().getString(R.string.history_week_detail_label));
                showWeeklyDetailChart(db.getWeeklyAdapter().getPreviousDetails(),
                        getResources().getString(R.string.history_week_prev_detail_label));
                showWeeklyHistoryChart(db.getWeeklyAdapter().getHistoryAverage());
            }

        } else if (type.isMonthly()) {
            average = db.getMonthlyAdapter().getAverage();
            cost = db.getMonthlyAdapter().getCost();
            total = db.getMonthlyAdapter().getCount();

            // Show chart only if network is available
            if (this.isNetworkAvailable()) {
                showMonthlyDetailChart((TreeMap<Integer, SmokeCounter>) db.getMonthlyAdapter().getDetails());
                showMonthlyDetailChart((TreeMap<Integer, SmokeCounter>) db.getMonthlyAdapter().getPreviousDetails());
                showMonthlyHistoryChart(db.getMonthlyAdapter().getHistoryAverage(),
                        getResources().getString(R.string.history_month_histo_label));
                showMonthlyHistoryChart(db.getMonthlyAdapter().getHistoryCost(),
                        getResources().getString(R.string.history_month_cost_label));
            }
        }

        // Show chart only if network is available
        if (this.isNetworkAvailable()) {
            chartImageAdapter = new ImageAdapter(HistoryActivity.this);
            chartImageAdapter.init();
        }

    }

    /**
     * Method used to update the UI after called to initValues().
     */
    @Override
    public void updateUI() {
        Log.d(getLogTag(), "updateUI");

        // Show chart only if network is available
        if (this.isNetworkAvailable()) {
            chartGallery.setAdapter(chartImageAdapter);
        }

        String cigarette = getResources().getString(R.string.cigarette);
        String day = getResources().getString(R.string.day);

        String averageValueLabel =
                getResources().getString(R.string.history_average_label) + " " + average + " " + cigarette + " / "
                        + day;
        averageLabel.setText(averageValueLabel);

        String totalValueLabel =
                getResources().getString(R.string.history_total_label) + " " + total + " " + cigarette;
        totalLabel.setText(totalValueLabel);

        String costValueLabel = getResources().getString(R.string.history_cost_label);
        NumberFormat ccyNF = NumberFormat.getCurrencyInstance(Locale.getDefault());
        costLabel.setText(costValueLabel + " " + ccyNF.format(cost));
    }

    /**
     * Method used to generate the Monthly Detailed Chart.
     * 
     * @param countValues
     *            to display in the chart
     */
    protected void showMonthlyDetailChart(final TreeMap<Integer, SmokeCounter> countValues) {
        Log.d(getLogTag(), "showMonthlyDetailChart");

        /* Generate Data for chart(if available) */
        if (countValues.size() > 0) {

            int nbDaysWithValues = 0;
            int lastDayOfMonth = 31;
            int detailsMaxValue = -1;
            int month = -1;

            LineChart lc = new LineChart();

            SmokeCounter firstSmoke = countValues.get(countValues.firstKey());
            month = firstSmoke.getDate().get(Calendar.MONTH);

            lastDayOfMonth = Tools.getLastDayOfMonth(firstSmoke.getDate().get(Calendar.MONTH) /*-1*/);

            int newTotal = 0;

            for (int i = 1; i <= lastDayOfMonth; i++) {

                if (countValues.containsKey(i)) {
                    // Donnée dispo
                    SmokeCounter smoke = countValues.get(i);
                    lc.addDataValue(smoke.getValue());

                    newTotal += smoke.getValue();
                    nbDaysWithValues++;

                    if (smoke.getValue() > detailsMaxValue) {
                        detailsMaxValue = smoke.getValue();
                    }

                } else {
                    // Pas de données pour ce jour
                    lc.addDataValue(Chart.BLANK_VALUE);
                }
            }

            double currentAvg = newTotal / nbDaysWithValues;

            /* Create the chart and define all parameters */
            lc.setAvgLegend(getResources().getString(R.string.history_month_average_legend));
            lc.setValueLegend(getResources().getString(R.string.history_month_value_legend));
            lc.setMaxYValue(detailsMaxValue);
            lc.setMaxXValue(lastDayOfMonth);
            lc.setAverage(currentAvg);
            lc.setTitle(getResources().getString(R.string.history_month_detail_label) + " "
                    + Tools.getMonthLabel(this, month + 1));

            // listOfCharts.add(lc);
            addChart(lc);

        } else {
            Log.d(getLogTag(), "No data to display ...");
        }
    }

    /**
     * Method used to generate the Monthly History Chart.
     * 
     * @param averageValues
     *            values of the chart
     * @param title
     *            of the chart
     */
    protected void showMonthlyHistoryChart(final List<SmokeAverage> averageValues, final String title) {
        Log.d(getLogTag(), "showMontlhyHistoryChart");

        if (averageValues.size() > 0) {

            /* Create the chart and define all parameters */
            HistoChart hst = new HistoChart();

            double histoMaxValue = -1;

            for (SmokeAverage smoke : averageValues) {
                hst.addDataValue(smoke.getValue());
                hst.addColumnLabel(Tools.getMonthFirstLetter(this, Integer.valueOf(smoke.getLabel())));

                if (smoke.getValue() > histoMaxValue) {
                    histoMaxValue = smoke.getValue();
                }
            }

            hst.setMaxVal(new BigDecimal(histoMaxValue).intValue() + 1);
            hst.setTitle(title);

            addChart(hst);
            // listOfCharts.add(hst);

        } else {
            Log.d(getLogTag(), "No data to display ...");
        }
    }

    /**
     * Method used to generate the Weekly Detailed Chart.
     * 
     * @param countValues
     *            of the chart
     * @param title
     *            of the chart
     */
    protected void showWeeklyDetailChart(final Map<Integer, SmokeCounter> countValues, final String title) {
        Log.d(getLogTag(), "showWeeklyDetailChart");

        if (countValues.size() > 0) {

            int detailsMaxValue = -1;

            /* Create the chart and define all parameters */
            HistoChart hst = new HistoChart();

            for (SmokeCounter smoke : countValues.values()) {
                hst.addDataValue(smoke.getValue());
                hst.addColumnLabel(Tools.getDayFirstLetter(this, Integer.valueOf(smoke.getLabel())));
                if (smoke.getValue() > detailsMaxValue) {
                    detailsMaxValue = smoke.getValue();
                }
            }

            hst.setMaxVal(new BigDecimal(detailsMaxValue).intValue() + 1);
            hst.setBarColor("3072F3");
            hst.setTitle(title);

            // listOfCharts.add(hst);
            addChart(hst);

        } else {
            Log.d(getLogTag(), "No data to display ...");
        }
    }

    /**
     * Method used to generate the Weekly History Chart.
     * 
     * @param averageValues
     *            chart values
     */
    protected void showWeeklyHistoryChart(final List<SmokeAverage> averageValues) {
        Log.d(getLogTag(), "showWeeklyHistoryChart");

        if (averageValues.size() > 0) {

            double histoMaxValue = -1;

            /* Create the chart and define all parameters */
            HistoChart hst = new HistoChart();

            for (SmokeAverage smoke : averageValues) {
                hst.addDataValue(smoke.getValue());
                hst.addColumnLabel(smoke.getLabel());
                if (smoke.getValue() > histoMaxValue) {
                    histoMaxValue = smoke.getValue();
                }
            }

            hst.setMaxVal(new BigDecimal(histoMaxValue).intValue() + 1);
            hst.setTitle(getResources().getString(R.string.history_week_histo_label));

            // listOfCharts.add(hst);
            addChart(hst);

        } else {
            Log.d(getLogTag(), "No data to display ...");
        }
    }

    /** ************************************************************** **/
    /** ************************************************************** **/
    /** ************************************************************** **/

    class ImageAdapter extends BaseAdapter {

        private final Context mContext;
        private ImageView[] tabImgView;
        private final Drawable defaultDrawable;
        private final ImageView defaultView;

        private boolean[] imgUpdatedOK;
        private final boolean loadComplete = false;

        /**
         * Create a new image adapter for Chart view.
         * 
         * @param contextArg
         *            application context
         */
        public ImageAdapter(final Context contextArg) {
            Log.d(getLogTag(), "new ImageAdapter()");
            mContext = contextArg;

            defaultView = new ImageView(mContext);
            defaultDrawable = getResources().getDrawable(R.drawable.eryos);
            defaultView.setImageDrawable(defaultDrawable);
        }

        /**
         * Initialize the adapter.
         */
        public void init() {
            tabImgView = new ImageView[listOfCharts.size()];
            imgUpdatedOK = new boolean[listOfCharts.size()];

            for (int i = 0; i < tabImgView.length; i++) {
                tabImgView[i] = new ImageView(mContext);
                tabImgView[i].setImageDrawable(defaultDrawable);
                imgUpdatedOK[i] = false;
            }
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public View getView(final int position, final View convertView, final ViewGroup parent) {
            Log.d(getLogTag(), "getView : " + position + "/" + tabImgView.length);

            if (position < tabImgView.length && !imgUpdatedOK[position] && !loadComplete) {
                Log.d(getLogTag(), "getView - download : " + position);

                try {
                    Bitmap thumb = Chart.downloadChartAsBitmap(mContext, listOfCharts.get(position).getThumbURL());
                    listOfCharts.get(position).setThumbBitmap(thumb);
                    tabImgView[position].setImageBitmap(thumb);
                    imgUpdatedOK[position] = true;
                    tabImgView[position].setLayoutParams(new Gallery.LayoutParams(Chart.DEFAULT_THUMB_WIDTH,
                            Chart.DEFAULT_THUMB_HEIGHT));
                    checkLoadComplete();
                } catch (UnknownHostException e) {
                    Log.e(getLogTag(), "UnknownHostException", e);
                } catch (IOException e) {
                    Log.e(getLogTag(), "IOException", e);
                }

            } else {
                Log.d(getLogTag(), "getView - bitmap already downloaded : " + position);
            }
            return tabImgView[position];
        }

        @Override
        public int getCount() {
            Log.d(getLogTag(), "getCount: " + listOfCharts.size());
            return listOfCharts.size();
        }

        @Override
        public Object getItem(final int position) {
            Log.d(getLogTag(), "getItem: " + position);
            return tabImgView[position];
        }

        @Override
        public long getItemId(final int position) {
            Log.d(getLogTag(), "getItemId: " + position);
            return position;
        }

        @Override
        public boolean isEnabled(final int position) {
            Log.d(getLogTag(), "isEnabled: " + position + " : " + super.isEnabled(position));
            return super.isEnabled(position);
        }

        @Override
        public int getViewTypeCount() {
            Log.d(getLogTag(), "getViewTypeCount: " + super.getViewTypeCount());
            return super.getViewTypeCount();
        }

        @Override
        public View getDropDownView(final int position, final android.view.View convertView,
                final android.view.ViewGroup parent) {
            Log.d(getLogTag(), "getDropDownView: " + position);
            return super.getDropDownView(position, convertView, parent);
        }

        @Override
        public int getItemViewType(final int position) {
            Log.d(getLogTag(), "getItemViewType: " + position);
            return super.getItemViewType(position);
        }

        /**
         * Verify if all download are complete or not.
         */
        public void checkLoadComplete() {
            boolean res = true;
            for (boolean load : imgUpdatedOK) {
                res = res && load;
            }

            Log.d(getLogTag(), "checkLoadComplete : " + res);

            if (res) {
                hideWaitingMessage();
            }
        }
    }

    /**
     * Method used to defined all UI handlers.
     */
    @Override
    public void initHandlers() {
        Log.d(getLogTag(), "initHandlers");

        // Show chart only if network is available
        if (this.isNetworkAvailable()) {
            initChartsHandlers();
        }

        showStatButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View view) {
                if (type.isWeekly()) {
                    showView(VIEW.MONTHLY);
                } else if (type.isMonthly()) {
                    showView(VIEW.WEEKLY);
                }
            }
        });

        homeButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(final View view) {
                showView(VIEW.HOME);
            }
        });
    }

    public void initChartsHandlers() {
        Log.d(getLogTag(), "initChartsHandlers");

        chartGallery.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(final AdapterView<?> arg0, final View arg1, final int position, final long id) {
                chartTitle.setText(listOfCharts.get(position).getTitle());
            }

            @Override
            public void onNothingSelected(final AdapterView<?> arg0) {
            }
        });

        chartGallery.setOnItemClickListener(new OnItemClickListener() {
            @Override
            @SuppressWarnings("rawtypes")
            public void onItemClick(final AdapterView parent, final View view, final int position, final long id) {
                new ChartPopup(HistoryActivity.this, listOfCharts.get(position));
            }
        });
    }

    @Override
    public void hideWaitingMessageAfterLoad() {
        Log.d("HistoryActivity", "overriden HideWaitingMessage");
        hideWaitingMessage();
    }
}
